<template>
    <view style="height: 100%">
        <view class="l-form-container-class">
            <slot />
        </view>
        <view class="l-form-btn-class">
            <view class="l-form-submit-class" mut-bind:tap="submit">
                <slot name="submit" />
            </view>
            <view class="l-form-reset-class" mut-bind:tap="reset">
                <slot name="reset" />
            </view>
        </view>
    </view>
</template>

<script>
import eventBus from '../core/utils/event-bus.js';
import eventUtil from '../core/utils/event-util';
export default {
    unicomGroup: ['form-item'],
    data() {
        return {
            _this: null
        };
    },
    externalClasses: ['l-form-container-class', 'l-form-submit-class', 'l-form-reset-class', 'l-form-btn-class'],
    options: {
        multipleSlots: true
    },
    relations: {
        '../form-item/index': {
            type: 'child',
            linked: function (t) {
                this._initItem(t);
            },
            linkChanged: function () {},
            unlinked: function () {}
        }
    },
    props: {
        name: {
            type: String,
            default: ''
        },
        isSubmitValidate: {
            type: Boolean,
            default: true
        }
    },
    mounted() {
        // 处理小程序 attached 生命周期
        this.attached();
    },
    destroyed() {
        for (let t in this._keys) {
            if (Object.prototype.hasOwnProperty.call(this._keys, t)) {
                eventBus.off('lin-form-blur-' + t);
                eventBus.off('lin-form-change-' + t);
            }
        }
    },
    methods: {
        attached() {
            this._init();
        },

        _init() {
            uni.lin = uni.lin || {};
            uni.lin.forms = uni.lin.forms || {};
            uni.lin.forms[this.name] = this;
            uni.lin.initValidateForm = (t) => {
                uni.lin._instantiation = t;
            };
            uni.lin.submitForm = function (t) {
                uni.lin.forms[t].submit();
            };
            uni.lin.resetForm = function (t) {
                uni.lin.forms[t].reset();
            };
        },

        _initItem(t) {
            this._keys = this._keys || {};
            this._errors = this._errors || {};
            const e = t.properties.name;
            eventBus.on('lin-form-blur-' + e, (t) => {
                this._validateItem(t, 'blur');
            });
            eventBus.on('lin-form-change-' + e, (t) => {
                clearTimeout(this.change_time);
                this.change_time = setTimeout(() => {
                    this._validateItem(t, 'change');
                }, 200);
            });
            if (this._keys[e]) {
                throw new Error('表单项存在重复的name：' + e);
            }
            this._keys[e] = '';
            this._errors[e] = [];
        },

        _validateItem(t, e) {
            let i = uni.lin._instantiation;
            let s = this._getValues();
            const r = this.getRelationNodes('form-item').find((e) => e.properties.name === t);
            if (!i.selectComponent('#' + t)) {
                throw new Error('表单项不存在name：' + t);
            }
            r.validatorData(s, e);
            this._errors[t] = r.data.errors;
            return r.data.errors;
        },

        _forEachNodes(t, e) {
            let i = this.getRelationNodes('form-item');
            if (e) {
                i.reverse();
            }
            i.forEach((e, i) => {
                t(e, i);
            });
        },

        _validateForm() {
            let t = uni.lin._instantiation;
            let e = [];
            let i = this._getValues();
            this._forEachNodes((s) => {
                const r = s.properties.name;
                if (!t.selectComponent('#' + r)) {
                    throw new Error('表单项不存在name：' + r);
                }
                s.validatorData(i);
                this._errors[r] = s.data.errors;
                e = e.concat(s.data.errors);
            }, true);
            return e;
        },

        _getValues() {
            let t = {};
            let e = uni.lin._instantiation;
            this._forEachNodes((i) => {
                const s = i.properties.name;
                const r = e.selectComponent('#' + s);
                if (r) {
                    t[s] = r.getValues();
                }
            });
            return t;
        },

        submit() {
            let t = this.isSubmitValidate ? this._validateForm() : [];
            this.$emit('linsubmit', {
                detail: {
                    values: this._getValues(),
                    errors: this.isSubmitValidate ? this._errors : {},
                    isValidate: 0 === t.length
                }
            });
        },

        reset() {
            let t = uni.lin._instantiation;
            this._forEachNodes((e) => {
                e.setData({
                    errorText: ''
                });
                const i = e.properties.name;
                const s = t.selectComponent('#' + i);
                if (s) {
                    s.reset();
                }
            });
            eventUtil.emit(this, 'linreset');
        }
    },
    created: function () {}
};
</script>
<style></style>
